<?php

namespace App\Http\Controllers;

use Illuminate\Validation\Rule;
use Throwable;
use Exception;
use Carbon\Carbon;
use App\Models\User;
use App\Models\Audit;
use App\Models\Project;
use App\Models\Position;
use Illuminate\Http\Request;
use App\Models\System\SysLog;
use App\Package\Message\Message;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Facades\Excel;
use App\Repositories\UserRepository;
use Maatwebsite\Excel\Writers\CellWriter;
use App\Http\Requests\Logic\User\BindProject;
use App\Http\Requests\Logic\User\QueryResource;
use App\Http\Requests\Logic\User\StoreResource;
use App\Http\Requests\Logic\User\UpdateResource;
use App\Http\Requests\Logic\User\VettingRequest;
use App\Http\Requests\Logic\User\UserPermission;
use App\Http\Requests\Logic\User\QueryCollection;
use App\Http\Requests\Logic\User\DestroyResource;
use Maatwebsite\Excel\Writers\LaravelExcelWriter;
use Maatwebsite\Excel\Classes\LaravelExcelWorksheet;
use App\Http\Requests\Logic\User\BatchVettingRequest;
use App\Http\Requests\Logic\User\GetByProjectRequest;
use App\Http\Requests\Logic\User\UserPermissionDestroy;

/**
 * 人员管理控制器
 *
 * Date: 22/03/2018
 * @author George
 * @package App\Http\Controllers
 */
class UserController extends Controller
{
	protected $userRepository;

	/**
	 * UserController constructor.
	 * @param $userRepository
	 */
	public function __construct(UserRepository $userRepository)
	{
		$this->userRepository = $userRepository;
	}

	/**
	 * 获取所有用户信息
	 *
	 * Date: 12/04/2018
	 * @author George
	 * @param QueryCollection $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function index(QueryCollection $request)
	{
		$name = $request->get('name');
		$mobile = $request->get('mobile');
		$status = $request->get('status');
		$project_id = $request->get('project_id');
		$position_id = $request->get('position_id');
		$certificate = $request->get('certificate');
		$export = $request->get('export');
		$start = $request->get('start');
		$end = $request->get('end');
		$paginate = $request->get('paginate', 15);
		$query = DB::table('company_user_pivot')->select([
			'users.id', 'users.name', 'users.certificate', 'mobile',
			'projects.name as project',
			'companies.title as company',
			'positions.name as position',
			'hiredate_at', 'departure_at'
		])->where('company_user_pivot.company_id', Auth::user()->company_id)
			->join('users', 'company_user_pivot.user_id', '=', 'users.id')
			->leftJoin('projects', 'users.project_id', '=', 'projects.id')
			->leftJoin('companies', 'company_user_pivot.company_id', '=', 'companies.id')
			->leftJoin('positions', 'users.position_id', '=', 'positions.id');

		if ($name) {
			$query->where('users.name', 'like', $name);
		}

		if ($mobile) {
			$query->where('users.mobile', $mobile);
		}

		if ($status === 'working') {
			$query->whereNull('departure_at');
		}

		if ($status === 'departure') {
			$query->whereNotNull('departure_at');
		}

		if ($project_id) {
			$query->where('users.project_id', $project_id);
		}

		if ($position_id) {
			$query->where('users.position_id', $position_id);
		}

		if ($certificate === 'licensed') {
			$query->whereNotNull('users.certificate');
		}

		if ($start && $end) {
			$query->whereBetween('company_user_pivot.hiredate_at', [$start, $end]);
		}

		if ($certificate === 'unlicensed') {
			$query->whereNull('users.certificate');
		}

		/**
		 * 导出数据
		 */
		if ($export) {
			Excel::create('users', function ($excel) use ($query) {
				/**
				 * @var LaravelExcelWriter $excel
				 */
				$excel->sheet('项目列表', function($sheet) use ($query) {
					/**
					 * 设置列宽度
					 * @var LaravelExcelWorksheet $sheet
					 */
					$sheet->setWidth(array(
						'A'     =>  10,
						'B'     =>  30,
						'C'     =>  20,
						'D'     =>  20,
						'E'     =>  20,
						'F'     =>  10,
						'G'     =>  15,
					));

					/**
					 * 设置对其方式
					 */
					$sheet->cells('A:G', function($cells) {
						/**
						 * @var CellWriter $cells
						 */
						$cells->setAlignment('center');
					});

					$sheet->fromArray($query->get()->map(function ($item) {
						return [
							'人员姓名'=> $item->name,
							'所属项目' => $item->name ?: '未分配项目',
							'有无保安证' => $item->certificate ?: '无',
							'职位' => $item->position ?: '未指定岗位',
							'入职时间' => substr($item->hiredate_at, 0, 10),
							'状态' => $item->departure_at ? '离职' : '在职',
							'手机号' => $item->mobile,
						];
					}));
				});
			})->download('xlsx');
            SysLog::log(Auth::user(),'人员管理模块','导出人员数据');

        }

		return success($query->paginate($paginate));
	}

	/**
	 * 获取指定用户详情信息
	 *
	 * Date: 12/04/2018
	 * @author George
	 * @param QueryResource $request
	 * @param $user_id
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function show(QueryResource $request, $user_id)
	{
		$user = User::with('personal', 'identificationInfo', 'company', 'project', 'department', 'position')->where('id', $user_id)->first();
		$record = DB::table('company_user_pivot')->where('company_id', Auth::user()->company_id)->where('user_id', $user_id)->latest('hiredate_at')->first();
		if ($record) {
			$user->hiredate_at = $record->hiredate_at;
			$user->departure_at = $record->departure_at;
			$user->fingerprint = $record->fingerprint;
			$user->transaction = $record->transaction;
			$user->dormitory = $record->dormitory;
			$user->expiry = $record->expiry;
		}
		return success($user);
	}

	/**
	 * 获取人员流动数据
	 *
	 * Date: 2018/6/29
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function turnover(Request $request)
	{
		$this->validate($request, [
			'company_id' => 'required',
			'month' => 'required',
			'type' => ['required', Rule::in(['hiredate_at', 'departure_at'])]
		]);
		$string = $request->get('month');
		$year = substr($string, 0, 4);
		$month = substr($string, 5, 2);
		$type = $request->get('type');

		$user = Auth::user();
		$company_id = $request->get('company_id', $user->company_id);
		$users = DB::table('company_user_pivot')
			->select(['users.id', 'users.name', 'users.avatar', 'positions.name as position_name', 'company_user_pivot.hiredate_at', 'company_user_pivot.departure_at'])
			->whereYear($type, $year)
			->whereMonth($type, $month)
			->where('company_user_pivot.company_id', $company_id)
			->leftJoin('users', 'company_user_pivot.user_id', '=', 'users.id')
			->leftJoin('positions', 'users.position_id', '=', 'positions.id')
			->get();
		return success($users);
	}

	/**
	 * 创建用户
	 *
	 * Date: 2018/5/21
	 * @author George
	 * @param StoreResource $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function store(StoreResource $request)
	{
		$message = new Message();

		$result = $message->verification($request->get('mobile'), $request->get('code'));
		if (!$result) {
			return failed('验证码错误', 422);
		}
		// 用户基础属性
		$userAttributes = $request->only([
			'name', 'mobile', 'password', 'birthday',
			'gender', 'identification', 'company_id',
			'department_id', 'project_id', 'position_id', 'certificate'
		]);

		// 用户个人信息
		$personalAttributes = $request->only([
			'stature', 'education', 'address',
			'marital', 'urgency_name', 'urgency_mobile', 'urgency_relation', 'trade',
			'skill', 'channel', 'debit'
		]);

		// 用户身份信息
		$identificationAttributes = $request->only([
			'issuer', 'hometown',
			'identification_front',
			'identification_reverse'
		]);

		// 用户和公司的关系
		$company_user_relation = $request->only([
			'hiredate_at', 'fingerprint',
			'transaction', 'dormitory',
			'expiry'
		]);

		try {
			DB::beginTransaction();
			$user = User::create($userAttributes);
			$user->companies()->attach($userAttributes['company_id'], $company_user_relation);
			$user->personal()->create($personalAttributes);
			$user->identificationInfo()->create($identificationAttributes);
            SysLog::log(Auth::user(),'人员管理模块','创建人员');
            DB::commit();
			return stored($user);
		} catch (Exception $exception) {
			DB::rollBack();
			dd($exception->getMessage());
			return internalError('创建用户失败');
		}
	}

	/**
	 * 更新用户
	 *
	 * Date: 12/04/2018
	 * @author George
	 * @param UpdateResource $request
	 * @param User $user
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function update(UpdateResource $request, User $user)
	{
		// 用户基础属性
		$userAttributes = $request->only([
			'name', 'mobile', 'birthday',
			'gender', 'identification', 'company_id',
			'department_id', 'project_id', 'position_id', 'certificate'
		]);

		// 用户个人信息
		$personalAttributes = $request->only([
			'stature', 'education', 'address',
			'marital', 'urgency_name', 'urgency_mobile', 'urgency_relation', 'trade',
			'skill', 'debit'
		]);

		$personalAttributes['channel'] = json_encode($request['channel']);
		$personalAttributes['trade'] = json_encode($request['trade']);
		$personalAttributes['skill'] = json_encode($request['skill']);

		// 用户身份信息
		$identificationAttributes = $request->only([
			'issuer', 'hometown',
			'identification_front',
			'identification_reverse'
		]);

		// 用户和公司的关系
		$company_user_relation = $request->only([
			'hiredate_at', 'fingerprint',
			'transaction', 'dormitory',
			'expiry'
		]);

		try {
			DB::beginTransaction();
			$user->update($userAttributes);
			$user->companies()->updateExistingPivot($userAttributes['company_id'], $company_user_relation);
			$user->personal()->update($personalAttributes);
			$user->identificationInfo()->update($identificationAttributes);
            SysLog::log(Auth::user(),'人员管理模块','更新人员信息');
            DB::commit();
			return stored($user);
		} catch (Exception $exception) {
			DB::rollBack();
			Log::error($exception);
			return internalError('更新用户失败');
		}
	}

	/**
	 * 获取未审批的用户信息
	 *
	 * Date: 18/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function unapproved(Request $request)
	{
		$paginate = $request->get('paginate', 15);
		$user_name = $request->get('user_name');
		$gender = $request->get('gender');
		$age = $request->get('age');
		$start = $request->get('start');
		$end = $request->get('end');

		$user = Auth::user();
		$query = DB::table('audits')->selectRaw(
			'audits.id as audit_id,users.id as user_id,users.name,users.gender,users.birthday,users.mobile,audits.created_at,personals.stature'
		)
			->leftJoin('users', 'audits.auditable_id', '=', 'users.id')
			->leftJoin('personals', 'users.identification', '=', 'personals.identification')
			->where('audits.company_id', $user->company_id)
			->where('audits.status', '=', 'pending');

		if ($age) {
			$query->whereRaw('ROUND(DATEDIFF(CURDATE(), birthday)/365.2422) =' . $age);
		}

		if ($user_name) {
			$query->where('users.name', 'like', "%{$user_name}%");
		}

		if ($gender) {
			$query->where('users.gender', $gender);
		}

		if ($start && $end) {
			$query->whereBetween('audits.created_at', [$start . ' 00:00:01', $end . '23:59:59']);
		}

		return success($query->paginate($paginate));
	}

	/**
	 * 获取年龄分布
	 *
	 * Date: 18/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Support\Collection
	 */
	public function ageDistribution(Request $request)
	{
		$user = Auth::user();
		$ages = DB::table('users')->where('company_id', $user->company_id)->whereNotNull('birthday')
			->selectRaw('ROUND(DATEDIFF(CURDATE(), birthday)/365.2422) as age')
			->get();

		return success($ages);
	}

	/**
	 * 解聘员工
	 *
	 * Date: 09/05/2018
	 * @author George
	 * @param DestroyResource $request
	 * @param User $user
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function destroy(DestroyResource $request, User $user)
	{
		$handler = Auth::user();

		if ($user->id === $handler->id) {
			return failed('无法删除当前账户');
		}

		try {
			DB::beginTransaction();

			// 更新企业和用户的中间表
			DB::table('company_user_pivot')->where([
				['company_id', '=', $handler->company_id],
				['user_id', '=', $user->id]
			])->update([
				'departure_at' => date('Y-m-d H:i:s'),
				'score' => $request->get('score'),
				'comment' => $request->get('comment')
			]);

			$user->company_id = 0;
			$user->project_id = 0;
			$user->department_id = 0;
			$user->position_id = 0;
			$user->manager = 0;
			$user->saveOrFail();
            SysLog::log(Auth::user(),'人员管理模块','删除人员');
            DB::commit();
			return deleted();
		} catch (Throwable $exception) {
			DB::rollBack();
			Log::error($exception);
			return internalError('删除用户失败');
		}
	}

	/**
	 * 获取项目人员信息集合
	 *
	 * Date: 15/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function staffByProject(Request $request)
	{
		$exclude_project = $request->get('exclude_project');
		$paginate = $request->get('paginate', 15);

		$query = DB::table('company_user_pivot')->select([
			'users.id', 'users.name'
		])->where('company_user_pivot.company_id', Auth::user()->company_id)
			->join('users', 'company_user_pivot.user_id', '=', 'users.id');

		if ($exclude_project) {
			$query->where('users.project_id', '<>', $exclude_project);
		}

		return success($query->paginate($paginate));
	}

	/**
	 * 处理审核
	 *
	 * Date: 24/04/2018
	 * @author George
	 * @param VettingRequest $request
	 * @return \Illuminate\Http\JsonResponse
	 * @throws \Throwable
	 */
	public function vetting(VettingRequest $request)
	{
		$attributes = $this->extractInputFromRules($request, $request->rules());
		$audit_id = array_pull($attributes, 'audit_id');
		/**
		 * @var Audit $audit
		 */
		$audit = Audit::findOrFail($audit_id);
		if ($attributes['status'] === 'rejected') {
			$audit->update($attributes);
		} else {
			try {
				DB::beginTransaction();
				$attributes['approver_id'] = Auth::id();
				$attributes['approver_type'] = 'user';
				$audit->update($attributes);
				$user = $audit->auditable()->first();
				$user->company_id = $audit->company_id;
				$user->saveOrFail();
				DB::table('company_user_pivot')->insert([
					'company_id' => $audit->company_id,
					'user_id' => $audit->proposer,
					'hiredate_at' => Carbon::now()
				]);
                SysLog::log(Auth::user(),'人员管理模块','审核人员');
                DB::commit();
			} catch (Exception $exception) {
				DB::rollBack();
				return internalError('提交审核失败');
			}
		}

		return updated($audit);
	}

	/**
	 * 批量通过
	 *
	 * Date: 24/04/2018
	 * @author George
	 * @param BatchVettingRequest $request
	 * @return \Illuminate\Http\JsonResponse
	 * @throws \Throwable
	 */
	public function batchVetting(BatchVettingRequest $request)
	{
		$ids = $request->get('ids');
		$user = Auth::user();
		try {
			DB::beginTransaction();
			DB::table('audits')->whereIn('id', $ids)->update(['status' => 'accepted']);
			$users = DB::table('audits')->whereIn('id', $ids)->pluck('proposer');
			DB::table('users')->whereIn('id', $users)->update(['company_id' => $user->company_id]);
			$records = [];
			foreach ($users as $id) {
				$records[] = [
					'company_id' => $user->company_id,
					'user_id' => $id,
					'hiredate_at' => date('Y-m-d H:i:s'),
				];
			}
			DB::table('company_user_pivot')->insert($records);
            SysLog::log(Auth::user(),'人员管理模块','批量审核人员');
            DB::commit();
			return updated($records);
		} catch (Exception $exception) {
			DB::rollBack();
			Log::error($exception);
			return internalError('审核提交失败');
		}
	}

	/**
	 * 为人员绑定管理的项目
	 *
	 * Date: 2018/5/30
	 * @author George
	 * @param BindProject $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function bindProject(BindProject $request)
	{
		/**
		 * @var User $user
		 */
		$user = User::findOrFail($request->get('user_id'));
		$ids = $request->get('projects_id');
		// 过滤人员的主项目
		$index = array_search($user->project_id, $ids);
		if ($index !== false) {
			array_pull($ids, $index);
		}

		$pivots = [];
		foreach ($ids as $id) {
			$pivots[$id] = [
				'company_id' => Auth::user()->company_id,
				'type' => 'manager',
			];
		}
		$user->projects()->sync($pivots);
        SysLog::log(Auth::user(),'人员管理模块','为人员绑定管理项目');

        return success($ids);
	}

    /**
     * 创建用户和项目用户和权限关系
	 *
     * @param UserPermission $request
     * @return \Illuminate\Http\JsonResponse
     */
	public function user_permission(UserPermission $request)
    {
        $attributes = $this->extractInputFromRules($request, $request->rules());
		/**
		 * @var User $user
		 */
        $user = User::findOrFail($attributes['user_id']);
        $ids = $attributes['projects_id'];
        $permissions = $attributes['permissions_code'];

        // 过滤人员的主项目
        $index = array_search($user->project_id, $ids);
        if ($index !== false) {
            array_pull($ids, $index);
        }
        // 插入用户项目中间表
        $pivots = [];
        foreach ($ids as $id) {
            $pivots[$id] = [
                'company_id' => Auth::user()->company_id,
                'type' => 'manager',
            ];
        }

        try {
            DB::beginTransaction();
            // 插入用户项目中间表
            $user->projects()->sync($pivots);
            // 插入用户权限表
            $user->permissions()->sync($permissions);
            DB::commit();
        } catch (Exception $exception){
            DB::rollBack();
            return internalError('操作失败');
        }
        return success($user);
    }

    /**
     * 查看权限列表
     * @param QueryCollection $request
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function user_permission_index(QueryCollection $request)
    {
        $attributes = $this->extractInputFromRules($request, $request->rules());
        $paginate = $request->get('paginate', 15);
        $user = User::query()->has('permissions')->with('permissions','position','projects','project')->paginate($paginate);
        return success($user);
    }

    /**
     * 查看人员详细信息
     *
     * Date: 2018/6/4
     * @author Leon
     * @param QueryResource $request
     * @param $user_id
     * @return \Illuminate\Http\JsonResponse
     */
    public function user_permission_detail(QueryResource $request, $user_id)
    {
        $user = User::query()->with('permissions','position','projects','project')->where('id',$user_id)->first();
        return success($user);
    }

    /**
     * 删除所有绑定关系
     * @param UserPermissionDestroy $request
     * @param $user_id
     * @return \Illuminate\Http\JsonResponse
     */
    public function user_permission_delete(UserPermissionDestroy $request, $user_id)
    {
        $user = User::query()->where('id',$user_id)->first();
        $user->permissions()->detach();
        $user->projects()->detach();
        return deleted($user);
    }

    /**
     * 获取职位条件
     *
     * Date: 2018/6/5
     * @author Leon
     * @return \Illuminate\Http\JsonResponse
     */
    public function user_permission_position()
    {
        $company_id = Auth::user()->company_id;
        $positions = Position::query()->where('company_id',$company_id)->get();
        return success($positions);
    }

    /**
     * 获取用户条件
     *
     * Date: 2018/6/5
     * @author Leon
     * @param QueryCollection $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function user_permission_user(QueryCollection $request)
    {
        $name = $request->get('name');
        $company_id = Auth::user()->company_id;
        $position_id = $request->get('position_id');
        $users = User::query();
        if($name){
            $users->where('name','like','%'.$name.'%');
        }
        $data = $users->where('position_id',$position_id)->where('company_id',$company_id)->with('project','projects')->doesntHave('permissions')->get();
        return success($data);

    }

    /**
     * 获取根据拼音分类的项目
     *
     * Date: 2018/6/5
     * @author Leon
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Support\Collection
     */
    public function user_permission_project(Request $request)
    {

        $count = $request->post('count');
        $name = $request->post('name');
        $ids = $request->post('ids',[]);
        $company_id = Auth::user()->company_id;
        switch ($count){
            case 'AE':
                $start = 45217;
                $end = 47009;
                break;
            case 'FJ':
                $start = 47010;
                $end = 49061;
                break;
            case 'KO':
                $start = 49062;
                $end = 50621;
                break;
            case 'PT':
                $start = 50622;
                $end = 52697;
                break;
            case 'UZ':
                $start = 52698;
                $end = 55289;
                break;
            default:
                break;
        }
        if($count == 'other'){
            $projects = DB::table('projects')
                ->where('company_id',$company_id)
                ->whereRaw('ascii(name) < 127')
                ->orderByRaw('CONVERT(name USING gbk)')
                ->get();
            foreach ($projects as $index => $project){
                if(in_array($project->id,$ids)){
                    $projects->pull($index);
                }
            }
            return success($projects);
        }
        if($count == 'all'){
            $projects = DB::table('projects')
                ->where('company_id',$company_id)
                ->get();
            foreach ($projects as $index => $project){
                if(in_array($project->id,$ids)){
                    $projects->pull($index);
                }
            }
            return success($projects);
        }
        if($count){
            $projects = DB::table('projects')
                ->where('company_id',$company_id)
                ->whereRaw('CONV(HEX(left(CONVERT(name USING gbk),1)),16,10) between '.$start.' and '.$end)
                ->orderByRaw('CONVERT(name USING gbk)')
                ->get();
            foreach ($projects as $index => $project){
                if(in_array($project->id,$ids)){
                    $projects->pull($index);
                }
            }
            return success($projects);
        }

        if($name){
            $pj = Project::query();
            $data = $pj->where('name','like','%'.$name.'%')->where('company_id',$company_id)->get();
            return success($data);
        }
    }

    public function getUserByProject(GetByProjectRequest $request)
    {
        $company_id = $request->user()->company_id;
        $project_id = $request->get('project_id');
        $list = User::query()->where(['company_id'=>$company_id,'project_id'=>$project_id])->get();
        return success($list);
    }
}
